/*
 * PhotonRTOS础光实时操作系统 -- AUTOSAR任务内部实现
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef OS_TASK_INTERNAL_H
#define OS_TASK_INTERNAL_H

#include <autosar/task.h>
#include <photon/types.h>
#include <photon/cpu.h>
#include <photon/sched.h>
#include <photon/process.h>
#include <photon/irq.h>
#include <autosar/calllevel_internal.h>

extern uint64_t last_task_activate_time[MAX_CPUS];
#define percpu_last_task_activate_time last_task_activate_time[smp_processor_id()]

extern FUNC(void, OS_CODE) osek_activate_task(VAR(TaskType, AUTOMATIC) task_id);
extern FUNC(void, OS_CODE) osek_deactivate_task(VAR(TaskType, AUTOMATIC) task_id);
extern FUNC(void, OS_CODE) osek_task_change_prio(VAR(TaskType, AUTOMATIC) task_id,
	VAR(int32_t, AUTOMATIC) prio);
extern FUNC(void, OS_CODE) osek_task_wakeup(VAR(TaskType, AUTOMATIC) task_id);
extern FUNC(void, OS_CODE) osek_yield(void);
extern FUNC(void, OS_CODE) osek_init_task(VAR(TaskType, AUTOMATIC)TaskID);
extern FUNC(void, OS_CODE) osek_interrupt_restore(void);
extern FUNC(void, OS_CODE) osek_release_all_resource(void);
extern FUNC(void, OS_CODE) attrs_to_alarm(VAR(int32_t, AUTOMATIC) i);
extern FUNC(void, OS_CODE) attrs_to_task(VAR(int32_t, AUTOMATIC) i);

extern VAR(struct task_desc, AUTOMATIC) osek_tasks[OS_NR_TASK];

/**
 * 判断是否位于OSEK任务上下文
 */
LOCAL_INLINE FUNC(int32_t, OS_CODE) in_osek_task(void)
{
	if ((!in_interrupt())
		&& (current->flags & TF_OSEK)) {
		return 1;
	}

	return 0;
}

/**
 * 当前任务ID
 */
LOCAL_INLINE FUNC(int32_t, OS_CODE) osek_current_id(void)
{
	return current->osek_id;
}

FUNC(StatusType, OS_CODE) __osek_activate_task(
	VAR(TaskType, AUTOMATIC) TaskID);

void os_check_async_action(void);

#if defined(AUTOSAR_SHOW_TASK_INFO)
/**
 * 可获取任务信息的数据结构
 */
struct task_info {
	/**
	 * 启动核心ID
	 */
	int32_t		core_id;

	/**
	 * autosar application id
	 */
	uint32_t	app_id;

	/**
	 * OSEK编号
	 */
	uintptr_t	osek_id;

	/**
	 * 任务是否为OSEK任务，拓展任务
	 */
	uint32_t	flags;

	/**
	 * 任务当前状态，如TASK_INTERRUPTIBLE
	 */
	volatile uintptr_t	state;

	/**
	 * 堆栈的总大小
	 */
	size_t		stack_size;

	/**
	 * 堆栈使用百分比
	 */
	uint8_t		stack_used;

	/**
	 * 任务调度优先级，当前按此优先级进行调度
	 * 可能比创建时的优先级有所提高或者降低
	 */
	int32_t		sched_prio;

	/**
	 * 任务优先级，创建时的优先级
	 */
	int32_t		prio;

	/**
	 * 多次激活的总运行时间(ms)
	 */
	uint32_t	all_run_time;

	/**
	 * cp 任务本次激活的实际执行时间
	 */
	uint32_t 	curr_run_time;

	/**
	 * cp 任务本次激或的预算总执行时间
	 */
	uint32_t 	execution_budget;

	/**
	 * 该任务最多可以激活的次数
	 */
	int32_t		max_activate_count;

	/**
	 * 激活次数
	 * 对于基本任务来说，可以激活多次
	 */
	int32_t		activate_count;

	/**
	 * 事件掩码，已经发送但是还没有被任务处理的事件
	 */
	uintptr_t	event_mask;

	/**
	 * 正在等待的事件
	 */
	uintptr_t	event_wait;

	/**
	 * 持有的资源数量
	 */
	int32_t		resource_count;

	/**
	 * 资源掩码，已经获取的资源
	 */
	uintptr_t	resource_mask;

	/**
	 * 应用模式
	 */
	AppModeType	app_mode;

	/**
	 * 是否自动启动
	 */
	int32_t		auto_start;
};

/* 获取的任务信息到缓冲区 */
extern VAR(struct task_info, AUTOMATIC) all_task_info[OS_NR_TASK];

/**
 * 更新任务信息缓冲区
 * base:    BASE_INFO(基本信息)，EXT_INFO(拓展信息)
 * osek_id: ALL_TASK(所有任务)，0,1,2...
 * 
 * 更新所有任务信息时，返回更新的任务数
 * 更新指定任务信息时，返回osek_id表示更新失败，返回osek+1表示更新成功
 */
FUNC(uintptr_t, OS_CODE) update_task_info(
	VAR(uint32_t, AUTOMATIC) base,
	VAR(uintptr_t, AUTOMATIC) osek_id);
#endif /* defined(AUTOSAR_SHOW_TASK_INFO) */

#endif /* OS_TASK_INTERNAL_H */
